﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace MT4Trainer
{
    using Encog.Engine.Network.Activation;
    using Encog.ML;
    using Encog.ML.Bayesian;
    using Encog.ML.HMM;
    using Encog.ML.SVM;
    using Encog.Neural.ART;
    using Encog.Neural.BAM;
    using Encog.Neural.CPN;
    using Encog.Neural.NEAT;
    using Encog.Neural.Networks;
    using Encog.Neural.PNN;
    using Encog.Neural.Pattern;
    using Encog.Neural.RBF;
    using Encog.Neural.SOM;
    using Encog.Neural.Thermal;

    public partial class NetworkCreator : Form
    {
        public NetworkCreator()
        {
            InitializeComponent();
        }

        public NetworkCreator(ref BasicNetwork net)
        {
            InitializeComponent();
            refnet = net;
        }

        private BasicNetwork refnet;

        public SupportVectorMachine machineNet { get; set; }
        private bool isSVM = false;
        public BasicNetwork ChosenNetwork { get; set; }


        private void NetworkCreator_Load(object sender, EventArgs e)
        {
            this.NetworkTypeComboBox.Items.AddRange(NetworkListTypes.GetGetNetworkTypes().ToArray());

            this.NetworkTypeComboBox.SelectedIndex = 0;

        }

        private void ValidateNetworkButton_Click(object sender, EventArgs e)
        {

            //Validate Inputs, checks that everything is filled...
            if (!ValidateInputs()) return;
            IMLMethod meth = GetMethodFromCombobox();



        }

        private bool ValidateInputs()
        {
            if (string.IsNullOrEmpty(InputCountTxtBox.Text))
            {
                this.richTextBox1.AppendText("Missing input in text box..");
                this.InputCountTxtBox.Select();
                return false;
            }
            if (string.IsNullOrEmpty(HiddenCountTxtBox.Text))
            {
                this.richTextBox1.AppendText("Missing Hidden 1 in text box..");
                this.HiddenCountTxtBox.Select();
                return false;
            }
            if (string.IsNullOrEmpty(HiddenCount2TxtBox.Text))
            {
                this.richTextBox1.AppendText("Missing Hidden 2 in text box..");
                this.HiddenCount2TxtBox.Select();
                return false;
            }
            if (string.IsNullOrEmpty(OutputCountTxtBox.Text))
            {
                this.richTextBox1.AppendText("Missing Output in text box..");
                this.OutputCountTxtBox.Select();
                return false;
            }

            if (string.IsNullOrEmpty(ActivationFunctionComboBox.Text))
            {
                this.richTextBox1.AppendText("Missing Activation function 1 in combo");
                this.ActivationFunctionComboBox.Select();
                return false;
            }

            if (string.IsNullOrEmpty(OutputActivationFunction.Text))
            {
                this.richTextBox1.AppendText("Missing output Activation function 1 in combo");
                this.OutputActivationFunction.Select();
                return false;
            }
            return true;
        }


        private IMLMethod GetMethodFromCombobox()
        {

            switch (this.NetworkTypeComboBox.Text)
            {
                case "":
                    break;
                case "Elman":
                    return GetElmanPattern();

                case "Adaline":
                    return CreateAdelinePattern();
                case "Art1":
                    return new ART1();

                case "BAM":
                    return new BAMNetwork();
                case "BoltzMann":
                    return new BoltzmannMachine();
                case "CPN":
                    return new CPNNetwork(20, 1, 20, 1);
                case "FeedForward":
                    return GetFeedForward();
                case "HopField":
                    return new HopfieldNetwork();
                case "Jordan":
                    return this.GetJordanPattern();
                case "PNN":
                    return new BasicPNN(PNNKernelType.Gaussian, PNNOutputMode.Regression, 20, 1);
                case "SOM":
                    return new SOMNetwork();
                case "RadialBasis":
                    return new RBFNetwork();
                case "SVM":
                    return GetSVMPattern();
                case "Neat":
                    return this.CreateNeatNet();
                case "Bayes":
                    return new BayesianNetwork();
                case "Markov":
                    return GetMarkovPattern();

                default:
                    break;


            }
            return new BasicNetwork();
        }


        #region create network by combox box chosen stuff.


        private IMLMethod GetSVMPattern()
        {
            SVMPattern patt = new SVMPattern();
            if (ActivationFunctionComboBox.Text.Contains("ActivationTANH"))
            {
                patt.ActivationFunction = new ActivationTANH();
            }
            else
            {
                patt.ActivationFunction = new ActivationSigmoid();
            }
            patt.InputNeurons = Convert.ToInt16(InputCountTxtBox.Text);
            patt.OutputNeurons = Convert.ToInt16(OutputCountTxtBox.Text);
            patt.AddHiddenLayer(Convert.ToInt16(HiddenCountTxtBox.Text));
            if (Convert.ToInt16(HiddenCount2TxtBox.Text) > 0)
                patt.AddHiddenLayer(Convert.ToInt16(HiddenCount2TxtBox.Text));

            this.machineNet = new SupportVectorMachine(patt.InputNeurons,SVMType.NewSupportVectorRegression,KernelType.Sigmoid);

            
            return (IMLMethod)patt;

        }
        private IMLMethod GetFeedForward()
        {
            return this.GetFeedforwardPattern();
        }

        private IMLMethod GetMarkovPattern()
        {
            HiddenMarkovModel mod = new HiddenMarkovModel(Convert.ToInt16(this.InputCountTxtBox.Text));

            return mod;
        }



        private IMLMethod CreateAdelinePattern()
        {
            if (ActivationFunctionComboBox.Text.Contains("ActivationTANH"))
            {
                var x = this.CreateADALINENetwork(
                    new ActivationTANH(),
                    Convert.ToInt16(InputCountTxtBox.Text),
                    Convert.ToInt16(this.OutputCountTxtBox.Text),
                    Convert.ToInt16(this.HiddenCountTxtBox.Text),
                    Convert.ToInt16(this.HiddenCount2TxtBox.Text));

                return x;
            }

            if (string.Compare(ActivationFunctionComboBox.Text, "ActivationSigmoid", StringComparison.InvariantCultureIgnoreCase) == 0)
            {

            }
            if (ActivationFunctionComboBox.Text.Contains("ActivationSigmoid"))
            {
                var x = this.CreateADALINENetwork(
                    new ActivationSigmoid(),
                    Convert.ToInt16(InputCountTxtBox.Text),
                    Convert.ToInt16(this.OutputCountTxtBox.Text),
                     Convert.ToInt16(this.HiddenCountTxtBox.Text),
                    Convert.ToInt16(this.HiddenCount2TxtBox.Text));
                return x;
            }
            else
            {
                //lets return a TAHN..
                var x = this.CreateADALINENetwork(
                   new ActivationTANH(),
                   Convert.ToInt16(InputCountTxtBox.Text),
                   Convert.ToInt16(this.OutputCountTxtBox.Text),
                   Convert.ToInt16(this.HiddenCountTxtBox.Text),
                    Convert.ToInt16(this.HiddenCount2TxtBox.Text));
                return x;
            }
        }

        private IMLMethod GetElmanPattern()
        {
            if (ActivationFunctionComboBox.Text.Contains("ActivationTANH"))
            {
                this.richTextBox1.AppendText("Found activation tanh , creating elman pattern...");
                var x = this.CreateElmanNetwork(
                    new ActivationTANH(),
                    Convert.ToInt16(InputCountTxtBox.Text),
                    Convert.ToInt16(this.OutputCountTxtBox.Text),
                    Convert.ToInt16(this.HiddenCountTxtBox.Text));
                return x;
            }

            if (string.Compare(ActivationFunctionComboBox.Text, "ActivationSigmoid", StringComparison.InvariantCultureIgnoreCase) == 0)
            {

            }
            if (ActivationFunctionComboBox.Text.Contains("ActivationSigmoid"))
            {
                this.richTextBox1.AppendText("Found activation sigmoid , creating elman pattern...");
                var x = this.CreateElmanNetwork(
                    new ActivationSigmoid(),
                    Convert.ToInt16(InputCountTxtBox.Text),
                    Convert.ToInt16(this.OutputCountTxtBox.Text),
                    Convert.ToInt16(this.HiddenCountTxtBox.Text));
                return x;
            }
            else
            {
                //lets return a TAHN..
                var x = this.CreateElmanNetwork(
                   new ActivationTANH(),
                   Convert.ToInt16(InputCountTxtBox.Text),
                   Convert.ToInt16(this.OutputCountTxtBox.Text),
                   Convert.ToInt16(this.HiddenCountTxtBox.Text));
                return x;
            }
        }


        private IMLMethod GetFeedforwardPattern()
        {
            if (ActivationFunctionComboBox.Text.Contains("ActivationTANH"))
            {
                this.richTextBox1.AppendText("Found activation tanh , creating elman pattern...");

                var p = Encog.Util.Simple.EncogUtility.SimpleFeedForward(
                    Convert.ToInt16(InputCountTxtBox.Text),
            Convert.ToInt16(this.HiddenCountTxtBox.Text),
                    Convert.ToInt16(this.HiddenCount2TxtBox.Text),
                    Convert.ToInt16(this.OutputCountTxtBox.Text),
                    true);

                return p;
            }

            if (string.Compare(ActivationFunctionComboBox.Text, "ActivationSigmoid", StringComparison.InvariantCultureIgnoreCase) == 0)
            {

            }
            if (ActivationFunctionComboBox.Text.Contains("ActivationSigmoid"))
            {
                this.richTextBox1.AppendText("Found activation sigmoid , creating elman pattern...");
                var p = Encog.Util.Simple.EncogUtility.SimpleFeedForward(
                    Convert.ToInt16(InputCountTxtBox.Text),
            Convert.ToInt16(this.HiddenCountTxtBox.Text),
                    Convert.ToInt16(this.HiddenCount2TxtBox.Text),
                    Convert.ToInt16(this.OutputCountTxtBox.Text),
                    false);
                return p;
            }
            else
            {
                //lets return a TAHN..
                var p = Encog.Util.Simple.EncogUtility.SimpleFeedForward(
                   Convert.ToInt16(InputCountTxtBox.Text),
           Convert.ToInt16(this.HiddenCountTxtBox.Text),
                   Convert.ToInt16(this.HiddenCount2TxtBox.Text),
                   Convert.ToInt16(this.OutputCountTxtBox.Text),
                   true);
                return p;
            }
        }
        private IMLMethod CreateNeatNet()
        {
            NEATNetwork net;
            if (ActivationFunctionComboBox.Text.Contains("ActivationTANH"))
            {
                this.richTextBox1.AppendText("Found activation tanh , creating Neat pattern...");

                net = new NEATNetwork(
                    Convert.ToInt16(InputCountTxtBox.Text), Convert.ToInt16(this.OutputCountTxtBox.Text));


                net.ActivationFunction = new ActivationTANH();

                return net;
            }

            if (string.Compare(ActivationFunctionComboBox.Text, "ActivationSigmoid", StringComparison.InvariantCultureIgnoreCase) == 0)
            {

            }
            if (ActivationFunctionComboBox.Text.Contains("ActivationSigmoid"))
            {
                this.richTextBox1.AppendText("Found activation SigMoid , creating Neat pattern...");
                net = new NEATNetwork(
                    Convert.ToInt16(InputCountTxtBox.Text), Convert.ToInt16(this.OutputCountTxtBox.Text));


                net.ActivationFunction = new ActivationSigmoid();

                return net;
            }
            else
            {
                net = new NEATNetwork(
                    Convert.ToInt16(InputCountTxtBox.Text), Convert.ToInt16(this.OutputCountTxtBox.Text));


                net.ActivationFunction = new ActivationSigmoid();

                return net;
            }

        }
        private IMLMethod GetJordanPattern()
        {
            if (ActivationFunctionComboBox.Text.Contains("ActivationTANH"))
            {
                this.richTextBox1.AppendText("Found activation tanh , creating Jordan pattern...");
                var x = this.CreateJordanNetwork(
                    new ActivationTANH(),
                    Convert.ToInt16(InputCountTxtBox.Text),
                    Convert.ToInt16(this.OutputCountTxtBox.Text),
                    Convert.ToInt16(this.HiddenCountTxtBox.Text));
                return x;
            }

            if (string.Compare(ActivationFunctionComboBox.Text, "ActivationSigmoid", StringComparison.InvariantCultureIgnoreCase) == 0)
            {

            }
            if (ActivationFunctionComboBox.Text.Contains("ActivationSigmoid"))
            {
                this.richTextBox1.AppendText("Found activation sigmoid , creating Jordan pattern...");
                var x = this.CreateJordanNetwork(
                    new ActivationSigmoid(),
                    Convert.ToInt16(InputCountTxtBox.Text),
                    Convert.ToInt16(this.OutputCountTxtBox.Text),
                    Convert.ToInt16(this.HiddenCountTxtBox.Text));
                return x;
            }
            else
            {
                //lets return a TAHN..
                var x = this.CreateJordanNetwork(
                   new ActivationTANH(),
                   Convert.ToInt16(InputCountTxtBox.Text),
                   Convert.ToInt16(this.OutputCountTxtBox.Text),
                   Convert.ToInt16(this.HiddenCountTxtBox.Text));
                return x;
            }
        }
        #endregion


        private void LoadNetworkButton_Click(object sender, EventArgs e)
        {
            using (var openfile = new OpenFileDialog())
            {
                if (openfile.ShowDialog() == DialogResult.OK)
                {
                    this.ChosenNetwork = Encog.Util.NetworkUtil.NetworkUtility.LoadNetwork(openfile.FileName);
                    this.InputCountTxtBox.Text = ChosenNetwork.InputCount.ToString();
                    this.OutputCountTxtBox.Text = ChosenNetwork.OutputCount.ToString();
                    var activs = ChosenNetwork.Flat.ActivationFunctions;
                    this.ActivationFunctionComboBox.Text = activs[0].ToString();
                    this.OutputActivationFunction.Text = activs[1].ToString();
                    this.HiddenCountTxtBox.Text = ChosenNetwork.Flat.NeuronCount.ToString();
                    this.richTextBox1.AppendText("Network infos :" + ChosenNetwork.ToString());
                }
            }
        }

        private void SendToMainButton_Click(object sender, EventArgs e)
        {
            refnet = this.ChosenNetwork;
            this.Close();
        }

        private void ExitPassButton_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void SaveNetworkButton_Click(object sender, EventArgs e)
        {

            this.richTextBox1.AppendText("Saving network to file...");
            using (var savediag = new SaveFileDialog())
            {
                if (savediag.ShowDialog() == DialogResult.OK)
                {
                    Encog.Util.NetworkUtil.NetworkUtility.SaveNetwork(savediag.FileName, ChosenNetwork);
                }
            }
        }


        #region net creation

        private IMLMethod CreateElmanNetwork(

            IActivationFunction activationFunctionfunc,
             int input = 2,
            int output = 1,
            int hidden = 5)
        {
            // construct an Elman type network
            var pattern = new ElmanPattern
            {
                ActivationFunction = activationFunctionfunc,
                InputNeurons = input
            };
            pattern.AddHiddenLayer(hidden);
            //No hidden 2 in elman or jordan network , they have context neurons.
            pattern.OutputNeurons = output;
            return pattern.Generate();
        }


        private IMLMethod CreateADALINENetwork(

            IActivationFunction activationFunctionfunc,
             int input = 2,
            int output = 1, int hidden2 = 0,
            int hidden = 5)
        {
            // construct an Elman type network
            var pattern = new ADALINEPattern()
            {
                ActivationFunction = activationFunctionfunc,
                InputNeurons = input
            };
            pattern.AddHiddenLayer(hidden);
            //We only add hidden2 if there are hidden 2..duh ...Lol.
            if (hidden2 > 0)
                pattern.AddHiddenLayer(hidden2);
            pattern.OutputNeurons = output;
            return pattern.Generate();
        }



        private IMLMethod CreateJordanNetwork(

    IActivationFunction activationFunctionfunc,
     int input = 2,
    int output = 1,
    int hidden = 5)
        {
            // construct an Elman type network
            var pattern = new JordanPattern()
            {
                ActivationFunction = activationFunctionfunc,
                InputNeurons = input
            };
            pattern.AddHiddenLayer(hidden);
            pattern.OutputNeurons = output;
            return pattern.Generate();
        }


        private static IMLMethod CreateFeedforwardNetwork(int input)
        {
            // construct a feedforward type network
            var pattern = new FeedForwardPattern();
            pattern.ActivationFunction = new ActivationSigmoid();
            pattern.InputNeurons = input;
            pattern.AddHiddenLayer(5);
            pattern.OutputNeurons = 1;
            return pattern.Generate();
        }
        #endregion
    }
}
